# -*- coding: utf-8 -*-

#    OriginDB
#    Copyright (C) 2009  Jason Power <power.jg@gmail.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from PyQt4.QtGui import *
from PyQt4.QtCore import *

import math
from random import shuffle

from tools import RemoveConnection, colors


class Arrow(QGraphicsItem):

	height = 20
	minWidth = 20
	# Fattness of arrow as percentage of height
	arrowWidth = .4

	# Fatness of arrow end
	arrowSize = .2

	penWidth = 1

	def __init__(self):
		QGraphicsItem.__init__(self)

		self.rect = QRectF()
		self.width = 0

		self.color = QColor(255,255,255)

		self.startPos = QPointF(0, 0)
		self.endPos = QPointF(0, 0.1)

		self.angle = 0


	def calcGeometry(self):
		vector = self.endPos - self.startPos

		dist = math.sqrt(vector.x()**2 + vector.y()**2)
		if vector.x() != 0:
			angle = math.atan(vector.y() / vector.x())
		elif vector.y() > 0:
			angle = math.pi/2
		else:
			angle = -math.pi/2
		if vector.x() < 0:
			angle += math.pi

		mid = self.startPos + vector*.5
		self.width = max(dist, self.minWidth)

		self.rect = QRectF(-self.width/2, -self.height/2, self.width, self.height)
		self.prepareGeometryChange()

		self.setPos(mid)
		self.rotate(angle*180/math.pi - self.angle)
		self.angle = angle*180/math.pi

	def boundingRect(self):
		return self.rect

	def paint(self, painter, option, widget):
		painter.setRenderHint(QPainter.Antialiasing, True)

		#painter.drawRect(self.rect)

		alpha = self.height*self.arrowSize
		beta = self.height*self.arrowWidth
		#painter.drawPolygon(QPointF(-self.width/2.0, -alpha/2.0),QPointF(self.width/2.0, 0),QPointF(-self.width/2.0, alpha/2.0))
		painter.setBrush(QBrush(self.color))
		c2 = self.color.darker(150)
		c2.setAlpha(255)
		pen = QPen(c2)
		pen.setJoinStyle(Qt.RoundJoin)
		pen.setWidth(2)
		painter.setPen(pen)
		painter.drawPolygon(QPointF(-self.width/2.0, -beta/2.0),
							QPointF(self.width/2.0-alpha*1.414-beta/2, -beta/2.0),
							QPointF(self.width/2.0-self.height/2.0-alpha/1.414,
									-self.height/2.0+alpha/1.414),
							QPointF(self.width/2.0-self.height/2.0, -self.height/2.0),
							QPointF(self.width/2.0, 0),
							QPointF(self.width/2.0-self.height/2.0, self.height/2.0),
							QPointF(self.width/2.0-self.height/2.0-alpha/1.414,
									self.height/2.0-alpha/1.414),
							QPointF(self.width/2.0-alpha*1.414-beta/2, beta/2.0),
							QPointF(-self.width/2.0, beta/2.0))


class Connection(Arrow):

	def __init__(self, productReaction, reactantReaction, productVis, reactantVis, color=None):
		Arrow.__init__(self)

		self.productVis = productVis
		self.reactantVis = reactantVis
		self.productReaction = productReaction
		self.reactantReaction = reactantReaction

		if color:
			self.color = color
		else:
			shuffle(colors)
			color = colors[0]
			for color in colors:
				if productReaction.testColor(color) and reactantReaction.testColor(color):
					self.color = color
					break

		self.setZValue(5)


	def getSerial(self):
		thing = [self.productReaction.reaction, (self.reactantReaction.reaction, self.productVis.compound)]
		return thing


	def add(self):
		self.startPos = self.productReaction.getProductPosition(self.productVis)
		self.endPos = self.reactantReaction.getReactantPosition(self.reactantVis)

		self.productReaction.setCompoundColor(self.productVis, self.color)

		self.reactantReaction.setCompoundColor(self.reactantVis, self.color)

		self.reactantReaction.addConnectionToUpdate(self)
		self.productReaction.addConnectionToUpdate(self)

		self.calcGeometry()
		

	def remove(self):
		""" Called before connection is deleted so we can reset the color
			of the reaction compounds and remove the update
		"""
		self.reactantReaction.removeConnectionToUpdate(self)

		self.productReaction.removeConnectionToUpdate(self)
		
		self.productReaction.setCompoundColor(self.productVis, None)
		
		self.reactantReaction.setCompoundColor(self.reactantVis, None)

	def updateReactions(self):
		""" This is called when the reaction moves that we connected to
		"""
		self.endPos = self.reactantReaction.getReactantPosition(self.reactantVis)
		self.startPos = self.productReaction.getProductPosition(self.productVis)
		self.calcGeometry()

	def contextMenuEvent(self, event):
		menu = QMenu()
		remove = menu.addAction("Remove Connection")
		action = menu.exec_(event.screenPos())
		if action == remove:
			command = RemoveConnection(self, self.scene())
			self.scene().undoStack.push(command)
	

